fn main() {
    let mut s1 = gives_ownership();         // gives_ownership moves its return
    // value into s1
    println!("{}", s1);

    let len = calculate_length(&s1);

    println!("The length of '{}' is {}.", s1, len);

    let s2 = String::from("hello");     // s2 comes into scope

    let s3 = takes_and_gives_back(s2);  // s2 is moved into
//    s3.push_str(", world!");
//    println!("{}", s2);
    println!("{}", s3);

    // takes_and_gives_back, which also

    // moves its return value into s3
    change(&mut s1);
    println!("{}", s1);

    let r1 = &mut s1;
    println!("r1={}", r1);

    let r2 = &mut s1;
    println!("r2={}", r2);

    let reference_to_nothing = dangle();    let word = first_word(&s1);
    println!("{}", word);
    //s1.clear();
} // Here, s3 goes out of scope and is dropped. s2 goes out of scope but was
// moved, so nothing happens. s1 goes out of scope and is dropped.

fn first_word(s: &String) -> usize {
    let bytes = s.as_bytes();

    for (i, &item) in bytes.iter().enumerate() {
        println!("{}={}", i, item);
        if item == b' ' {
            return i;
        }
    }

    s.len()
}

fn dangle() -> String {
    let s = String::from("hello");

    s
}

fn change(some_string: &mut String) {
    some_string.push_str(", world");
}

fn calculate_length(s: &String) -> usize {
    s.len()
}

fn gives_ownership() -> String {
    // gives_ownership will move its
    // return value into the function
    // that calls it

    let some_string = String::from("hello"); // some_string comes into scope

    some_string                              // some_string is returned and
    // moves out to the calling
    // function
}

// takes_and_gives_back will take a String and return one
fn takes_and_gives_back(a_string: String) -> String {
    // a_string comes into
    // scope

    a_string  // a_string is returned and moves out to the calling function
}
